{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第5周作业\n",
    "作业要求：将triplet_dataset_sub_song_merged.csv中的数据用train_test_split分成60%数据做训练，剩下40%数据做测试。 \n",
    "1. 实现基于用户的协同过滤； （20分） \n",
    "2. 实现基于物品的协同过滤； （20分） \n",
    "3. 实现基于模型（矩阵分解/LFM）的协同过滤。（30分） \n",
    "4. 对每种推荐算法的推荐结果，用Top20个推荐歌曲的准确率和召回率评价推荐系统的性能。（30分） "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于计算机资源有限，采用老师给的精选数据文件，最活跃的前800个用户和最流行的800首歌曲。triplet_dataset_sub.csv文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 导入工具包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sn\n",
    "\n",
    "import scipy.io as sio\n",
    "import scipy.sparse as ss\n",
    "#相似度/距离\n",
    "import scipy.spatial.distance as ssd\n",
    "\n",
    "from collections import defaultdict\n",
    "from sklearn.preprocessing import normalize"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  读取数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user</th>\n",
       "      <th>song</th>\n",
       "      <th>play_count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>4e11f45d732f4861772b2906f81a7d384552ad12</td>\n",
       "      <td>SOCKSGZ12A58A7CA4B</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>4e11f45d732f4861772b2906f81a7d384552ad12</td>\n",
       "      <td>SOCVTLJ12A6310F0FD</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>4e11f45d732f4861772b2906f81a7d384552ad12</td>\n",
       "      <td>SODLLYS12A8C13A96B</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4e11f45d732f4861772b2906f81a7d384552ad12</td>\n",
       "      <td>SOEGIYH12A6D4FC0E3</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4e11f45d732f4861772b2906f81a7d384552ad12</td>\n",
       "      <td>SOFRQTD12A81C233C0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                       user                song  play_count\n",
       "0  4e11f45d732f4861772b2906f81a7d384552ad12  SOCKSGZ12A58A7CA4B           1\n",
       "1  4e11f45d732f4861772b2906f81a7d384552ad12  SOCVTLJ12A6310F0FD           1\n",
       "2  4e11f45d732f4861772b2906f81a7d384552ad12  SODLLYS12A8C13A96B           3\n",
       "3  4e11f45d732f4861772b2906f81a7d384552ad12  SOEGIYH12A6D4FC0E3           1\n",
       "4  4e11f45d732f4861772b2906f81a7d384552ad12  SOFRQTD12A81C233C0           2"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data=pd.read_csv(\"triplet_dataset_sub.csv\")\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 37519 entries, 0 to 37518\n",
      "Data columns (total 3 columns):\n",
      "user          37519 non-null object\n",
      "song          37519 non-null object\n",
      "play_count    37519 non-null int64\n",
      "dtypes: int64(1), object(2)\n",
      "memory usage: 879.4+ KB\n"
     ]
    }
   ],
   "source": [
    "data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>play_count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>16.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>73.187500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>176.069009</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>7.500000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>18.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>44.750000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>716.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       play_count\n",
       "count   16.000000\n",
       "mean    73.187500\n",
       "std    176.069009\n",
       "min      1.000000\n",
       "25%      7.500000\n",
       "50%     18.000000\n",
       "75%     44.750000\n",
       "max    716.000000"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "sn.countplot(data.user)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8.799221727657986"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data1=np.array(data)\n",
    "np.mean(data1[:,2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1.基于用户的协同过滤"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "用户给歌曲打分。用播放次数比例来打分。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [],
   "source": [
    "sum_data=data[[\"user\",\"play_count\"]].groupby(\"user\").sum().reset_index()  #通过对用户分组，统计出每个用户的音乐总播放量。\n",
    "sum_data.rename(columns={\"play_count\":\"total_play_count\"},inplace=True)  #改列名为total_play_count\n",
    "#\n",
    "data=pd.merge(data,sum_data)  #把total_play_count合并到原数据中。\n",
    "data[\"fractional_play_count\"]=data[\"play_count\"]/data[\"total_play_count\"]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 37519 entries, 0 to 37518\n",
      "Data columns (total 5 columns):\n",
      "user                     37519 non-null object\n",
      "song                     37519 non-null object\n",
      "play_count               37519 non-null int64\n",
      "total_play_count         37519 non-null int64\n",
      "fractional_play_count    37519 non-null float64\n",
      "dtypes: float64(1), int64(2), object(2)\n",
      "memory usage: 1.7+ MB\n"
     ]
    }
   ],
   "source": [
    "data.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "筛选出用户和歌曲"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用户数： 790 \n",
      "歌曲数： 800\n"
     ]
    }
   ],
   "source": [
    "\n",
    "users=list(data[\"user\"].unique())\n",
    "songs=list(data[\"song\"].unique())\n",
    "n_users=len(users)\n",
    "n_songs=len(songs)\n",
    "print(\"用户数：\",len(users),\"\\n歌曲数：\",len(songs))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "倒排表准备"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "metadata": {},
   "outputs": [],
   "source": [
    "user_songs=defaultdict(set) #每个用户播放过的歌曲\n",
    "song_users=defaultdict(set) #播放每个歌曲的用户\n",
    "\n",
    "#用户-歌曲关系矩阵表\n",
    "user_songs_scores=ss.dok_matrix((n_users,n_songs))\n",
    "\n",
    "# 重新编码用户索引字典\n",
    "users_index={}\n",
    "for i,u in enumerate(users):\n",
    "    users_index[u]=i\n",
    "#重新编码歌曲索引字典\n",
    "songs_index={}\n",
    "for i,s in enumerate(songs):\n",
    "    songs_index[s]=i"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "制作倒排表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_records=data.shape[0]\n",
    "for i in range(n_records):\n",
    "    user_index_i=users_index[data.iloc[i]['user']] #用户的索引\n",
    "    song_index_i=songs_index[data.iloc[i]['song']] #歌曲的索引\n",
    "    user_songs[user_index_i].add(song_index_i) #用户对应的歌曲的索引\n",
    "    song_users[song_index_i].add(user_index_i) #歌曲对应的用户的索引\n",
    "    score=data.iloc[i][\"fractional_play_count\"]  #播放次数的比例\n",
    "    user_songs_scores[user_index_i,song_index_i]=score  #存入用户歌曲关系矩阵中\n",
    "\n",
    "#保存倒排表\n",
    "pickle.dump(user_songs,open(\"user_songs.pkl\",\"wb\"))\n",
    "pickle.dump(song_users,open(\"song_users.pkl\",\"wb\"))\n",
    "    \n",
    "#保存用户-歌曲关系矩阵\n",
    "sio.mmwrite(\"user_songs_scores\",user_songs_scores)\n",
    "\n",
    "#保存用户索引表和歌曲索引表\n",
    "pickle.dump(users_index,open('users_index.pkl','wb'))\n",
    "pickle.dump(songs_index,open('songs_index.pkl','wb'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "计算用户之间的相似度，假设有两个用户，通过计算播放它们播放歌曲的相似度来计算用户之间的相似度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [],
   "source": [
    "similarity_matrix_user=np.matrix(np.zeros(shape=(n_users,n_users)),float)\n",
    "for i in range(n_users):\n",
    "    songs_i=user_songs[i]\n",
    "    similarity_matrix_user[i,i]=1 #相对于本身来说，相似度是1\n",
    "    for j in range(i+1,n_users):\n",
    "        songs_j=user_songs[j]\n",
    "        songs_intersection=songs_i.intersection(songs_j) #songs_i与songs_j的交集\n",
    "        if songs_intersection!=0:\n",
    "            songs_union=songs_i.union(songs_j) #songs_i与songs_j的并集\n",
    "            similarity_matrix_user[j,i]=len(songs_intersection)/len(songs_union) #相似度用交集除以并集\n",
    "        else:\n",
    "            similarity_matrix_user[j,i]=0 #如果没有交集，则相似度为0           \n",
    "    similarity_matrix_user[i,j]=similarity_matrix_user[j,i] #补充完整相似度矩阵\n",
    "pickle.dump(similarity_matrix_user,open('users_similarity.pkl',\"wb\")) #保存用户相似度矩阵"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 基于用户相似度推荐歌曲"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 229,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6b2787bcf47cfea75b734729cdaddd700137ad5a\n"
     ]
    }
   ],
   "source": [
    "cur_user=users[83] # 给定一个用户，然后做推荐。\n",
    "print(cur_user)\n",
    "cur_user_id=users_index[cur_user]\n",
    "cur_user_songs=user_songs[cur_user_id]  #该用户实际听过的歌曲\n",
    "\n",
    "n_cur_user_songs=len(cur_user_songs)\n",
    "user_sim_scores=np.zeros(n_cur_user_songs)\n",
    "\n",
    "cur_similarity_matrix=np.matrix(np.zeros(shape=(n_cur_user_songs,n_songs)),float) \n",
    "cur_song_index=0\n",
    "for i in cur_user_songs:\n",
    "    cur_similarity_matrix[cur_song_index,:]=similarity_matrix_user[i,0] #用户之间的相似度\n",
    "    cur_song_index+=1\n",
    "\n",
    "user_sim_scores=cur_similarity_matrix.sum(axis=0)/cur_similarity_matrix.shape[0]\n",
    "user_sim_scores=np.array(user_sim_scores)[0].tolist()  \n",
    "\n",
    "sort_index=sorted(((e,i) for i,e in enumerate(list(user_sim_scores))),reverse=True)\n",
    "columns=[\"user_id\",\"song\",\"score\",\"rank\"]\n",
    "df=pd.DataFrame(columns=columns)\n",
    "rank=1\n",
    "for i in range(len(sort_index)):\n",
    "    cur_song_index=sort_index[i][1]\n",
    "    cur_song=list(songs_index.keys())[list(songs_index.values()).index(cur_song_index)]\n",
    "    if ~np.isnan(sort_index[i][0]) and cur_song_index not in cur_user_songs and rank<21:\n",
    "        df.loc[len(df)]=[cur_user,cur_song,sort_index[i][0],rank]\n",
    "        rank+=1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 230,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>song</th>\n",
       "      <th>score</th>\n",
       "      <th>rank</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOZZTNF12A8C139916</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOYYKLS12A8C134802</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOLZOBD12AB0185720</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOXCBEF12A8C146AFE</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOZBDZN12A8C130C7B</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOVOKGC12A58A7DF6B</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOVEFXA12A58A7942A</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOUSQCN12A8C133302</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOUODFE12A58A80347</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOYUDDS12A6D4F7BD6</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOPTLTT12A58A7938D</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOYYCTP12AB017E29C</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOXFMAQ12A6D4F91E0</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOXTTHY12A8C137072</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOZVMYF12A8C132646</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>15</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOQQGBB12A6D4FCE33</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>16</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOXPSGF12AB0187589</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOQJHUW12AB0188A24</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOYYFLV12A58A7A88F</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>19</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>6b2787bcf47cfea75b734729cdaddd700137ad5a</td>\n",
       "      <td>SOYZOUY12AAF3B5B94</td>\n",
       "      <td>0.036666</td>\n",
       "      <td>20</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     user_id                song     score  \\\n",
       "0   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOZZTNF12A8C139916  0.036666   \n",
       "1   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOYYKLS12A8C134802  0.036666   \n",
       "2   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOLZOBD12AB0185720  0.036666   \n",
       "3   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOXCBEF12A8C146AFE  0.036666   \n",
       "4   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOZBDZN12A8C130C7B  0.036666   \n",
       "5   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOVOKGC12A58A7DF6B  0.036666   \n",
       "6   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOVEFXA12A58A7942A  0.036666   \n",
       "7   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOUSQCN12A8C133302  0.036666   \n",
       "8   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOUODFE12A58A80347  0.036666   \n",
       "9   6b2787bcf47cfea75b734729cdaddd700137ad5a  SOYUDDS12A6D4F7BD6  0.036666   \n",
       "10  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOPTLTT12A58A7938D  0.036666   \n",
       "11  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOYYCTP12AB017E29C  0.036666   \n",
       "12  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOXFMAQ12A6D4F91E0  0.036666   \n",
       "13  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOXTTHY12A8C137072  0.036666   \n",
       "14  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOZVMYF12A8C132646  0.036666   \n",
       "15  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOQQGBB12A6D4FCE33  0.036666   \n",
       "16  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOXPSGF12AB0187589  0.036666   \n",
       "17  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOQJHUW12AB0188A24  0.036666   \n",
       "18  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOYYFLV12A58A7A88F  0.036666   \n",
       "19  6b2787bcf47cfea75b734729cdaddd700137ad5a  SOYZOUY12AAF3B5B94  0.036666   \n",
       "\n",
       "   rank  \n",
       "0     1  \n",
       "1     2  \n",
       "2     3  \n",
       "3     4  \n",
       "4     5  \n",
       "5     6  \n",
       "6     7  \n",
       "7     8  \n",
       "8     9  \n",
       "9    10  \n",
       "10   11  \n",
       "11   12  \n",
       "12   13  \n",
       "13   14  \n",
       "14   15  \n",
       "15   16  \n",
       "16   17  \n",
       "17   18  \n",
       "18   19  \n",
       "19   20  "
      ]
     },
     "execution_count": 230,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 233,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "准确率是： 0.045454545454545456\n"
     ]
    }
   ],
   "source": [
    "user_song_true=[]\n",
    "for i,j in songs_index.items():\n",
    "    if j in cur_user_songs:\n",
    "        user_song_true.append(i)\n",
    "user_song_true=set(user_song_true)\n",
    "user_song_prd=set(df.song.values)\n",
    "precision=len(user_song_true.intersection(user_songs_prd))/len(user_song_true)\n",
    "print(\"准确率是：\",precision)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 234,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "召回率是： 0.1\n"
     ]
    }
   ],
   "source": [
    "recall=len(user_song_true.intersection(user_songs_prd))/len(user_songs_prd)\n",
    "print(\"召回率是：\",recall)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.基于物品的协同过滤"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "计算歌曲之间的相似度，假设有两首歌曲，每首歌曲都有用户播放它们，通过计算播放它们的用户群体的相似度来计算歌曲之间的相似度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [],
   "source": [
    "similarity_matrix=np.matrix(np.zeros(shape=(n_songs,n_songs)),float)\n",
    "for i in range(n_songs):\n",
    "    users_i=song_users[i]\n",
    "    similarity_matrix[i,i]=1 #相对于本身来说，相似度是1\n",
    "    for j in range(i+1,n_songs):\n",
    "        users_j=song_users[j]\n",
    "        users_intersection=users_i.intersection(users_j) #users_i与users_j的交集\n",
    "        if users_intersection!=0:\n",
    "            users_union=users_i.union(users_j) #users_i与users_j的并集\n",
    "            similarity_matrix[j,i]=len(users_intersection)/len(users_union) #相似度用交集除以并集\n",
    "        else:\n",
    "            similarity_matrix[j,i]=0 #如果没有交集，则相似度为0           \n",
    "    similarity_matrix[i,j]=similarity_matrix[j,i] #补充完整相似度矩阵\n",
    "pickle.dump(similarity_matrix,open('songs_similarity.pkl',\"wb\")) #保存歌曲相似度矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 221,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "e0152edeec1154b620b083fbb095f1f0f4de5e2e\n"
     ]
    }
   ],
   "source": [
    "cur_user=users[89] # 给定一个用户，然后做推荐。\n",
    "print(cur_user)\n",
    "cur_user_id=users_index[cur_user]\n",
    "cur_user_songs=user_songs[cur_user_id]  #该用户实际听过的歌曲\n",
    "\n",
    "n_cur_user_songs=len(cur_user_songs)\n",
    "user_sim_scores=np.zeros(n_cur_user_songs)\n",
    "\n",
    "cur_similarity_matrix=np.matrix(np.zeros(shape=(n_cur_user_songs,n_songs)),float) \n",
    "cur_song_index=0\n",
    "for i in cur_user_songs:\n",
    "    cur_similarity_matrix[cur_song_index,:]=similarity_matrix[i,0]\n",
    "    cur_song_index+=1\n",
    "\n",
    "user_sim_scores=cur_similarity_matrix.sum(axis=0)/cur_similarity_matrix.shape[0]\n",
    "user_sim_scores=np.array(user_sim_scores)[0].tolist()  #每首歌曲与其他歌曲的相似度。\n",
    "\n",
    "sort_index=sorted(((e,i) for i,e in enumerate(list(user_sim_scores))),reverse=True)\n",
    "columns=[\"user_id\",\"song\",\"score\",\"rank\"]\n",
    "df=pd.DataFrame(columns=columns)\n",
    "rank=1\n",
    "for i in range(len(sort_index)):\n",
    "    cur_song_index=sort_index[i][1]\n",
    "    cur_song=list(songs_index.keys())[list(songs_index.values()).index(cur_song_index)]\n",
    "    if ~np.isnan(sort_index[i][0]) and cur_song_index not in cur_user_songs and rank<21:\n",
    "        df.loc[len(df)]=[cur_user,cur_song,sort_index[i][0],rank]\n",
    "        rank+=1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 222,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>song</th>\n",
       "      <th>score</th>\n",
       "      <th>rank</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOZZTNF12A8C139916</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOYYKLS12A8C134802</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOLZOBD12AB0185720</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOXCBEF12A8C146AFE</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOZBDZN12A8C130C7B</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOVOKGC12A58A7DF6B</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOVEFXA12A58A7942A</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOUSQCN12A8C133302</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOUODFE12A58A80347</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOYUDDS12A6D4F7BD6</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOPTLTT12A58A7938D</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOYYCTP12AB017E29C</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOXFMAQ12A6D4F91E0</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOXTTHY12A8C137072</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOZVMYF12A8C132646</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>15</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOXPSGF12AB0187589</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>16</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOQJHUW12AB0188A24</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOYDHXP12AB01849D4</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOVPAJA12A58A77B15</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>19</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOYYFLV12A58A7A88F</td>\n",
       "      <td>0.14151</td>\n",
       "      <td>20</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     user_id                song    score rank\n",
       "0   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOZZTNF12A8C139916  0.14151    1\n",
       "1   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOYYKLS12A8C134802  0.14151    2\n",
       "2   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOLZOBD12AB0185720  0.14151    3\n",
       "3   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOXCBEF12A8C146AFE  0.14151    4\n",
       "4   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOZBDZN12A8C130C7B  0.14151    5\n",
       "5   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOVOKGC12A58A7DF6B  0.14151    6\n",
       "6   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOVEFXA12A58A7942A  0.14151    7\n",
       "7   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOUSQCN12A8C133302  0.14151    8\n",
       "8   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOUODFE12A58A80347  0.14151    9\n",
       "9   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOYUDDS12A6D4F7BD6  0.14151   10\n",
       "10  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOPTLTT12A58A7938D  0.14151   11\n",
       "11  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOYYCTP12AB017E29C  0.14151   12\n",
       "12  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOXFMAQ12A6D4F91E0  0.14151   13\n",
       "13  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOXTTHY12A8C137072  0.14151   14\n",
       "14  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOZVMYF12A8C132646  0.14151   15\n",
       "15  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOXPSGF12AB0187589  0.14151   16\n",
       "16  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOQJHUW12AB0188A24  0.14151   17\n",
       "17  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOYDHXP12AB01849D4  0.14151   18\n",
       "18  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOVPAJA12A58A77B15  0.14151   19\n",
       "19  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOYYFLV12A58A7A88F  0.14151   20"
      ]
     },
     "execution_count": 222,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "准确率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 227,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "准确率是： 0.029411764705882353\n"
     ]
    }
   ],
   "source": [
    "user_song_true=[]\n",
    "for i,j in songs_index.items():\n",
    "    if j in cur_user_songs:\n",
    "        user_song_true.append(i)\n",
    "user_song_true=set(user_song_true)\n",
    "user_song_prd=set(df.song.values)\n",
    "precision=len(user_song_true.intersection(user_songs_prd))/len(user_song_true)\n",
    "print(\"准确率是：\",precision)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "召回率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 228,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "召回率是： 0.05\n"
     ]
    }
   ],
   "source": [
    "recall=len(user_song_true.intersection(user_songs_prd))/len(user_songs_prd)\n",
    "print(\"召回率是：\",recall)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 226,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'SOCKSGZ12A58A7CA4B': 0,\n",
       " 'SOCVTLJ12A6310F0FD': 1,\n",
       " 'SODLLYS12A8C13A96B': 2,\n",
       " 'SOEGIYH12A6D4FC0E3': 3,\n",
       " 'SOFRQTD12A81C233C0': 4,\n",
       " 'SOHEMBB12A6701E907': 5,\n",
       " 'SOHJOLH12A6310DFE5': 6,\n",
       " 'SOIZLKI12A6D4F7B61': 7,\n",
       " 'SOJGSIO12A8C141DBF': 8,\n",
       " 'SOKEYJQ12A6D4F6132': 9,\n",
       " 'SOKLRPJ12A8C13C3FE': 10,\n",
       " 'SOKNWRZ12A8C13BF62': 11,\n",
       " 'SOKXYUW12A8C140229': 12,\n",
       " 'SOLAUOW12A8C13A400': 13,\n",
       " 'SOLLDVS12AB0183835': 14,\n",
       " 'SOLOZRE12A8C133256': 15,\n",
       " 'SOLWRZI12A6D4FC4F0': 16,\n",
       " 'SOMDVSL12A6D4F7230': 17,\n",
       " 'SOMGIYR12AB0187973': 18,\n",
       " 'SOMNGMO12A6702187E': 19,\n",
       " 'SOMRYYN12A6310F0F3': 20,\n",
       " 'SONDCOR12A8C13BA16': 21,\n",
       " 'SONQBUB12A6D4F8ED0': 22,\n",
       " 'SONYKOW12AB01849C9': 23,\n",
       " 'SOOALOT12A8C13ABD9': 24,\n",
       " 'SOOKGRB12A8C13CD66': 25,\n",
       " 'SOOSJIV12AF729E09E': 26,\n",
       " 'SOOZFCC12A58A7D783': 27,\n",
       " 'SOPBXPQ12AB01887E2': 28,\n",
       " 'SOPCTBB12AF72A1B64': 29,\n",
       " 'SOPJULC12A6D4F667F': 30,\n",
       " 'SOPQLBY12A6310E992': 31,\n",
       " 'SOPXLWJ12A8C132639': 32,\n",
       " 'SOPZVSB12A8C13E2EF': 33,\n",
       " 'SOQAJHW12AB0186004': 34,\n",
       " 'SOQFEDG12AB018DD24': 35,\n",
       " 'SOQGSUC12A8C13B66D': 36,\n",
       " 'SOQIOXQ12AAF3B2A37': 37,\n",
       " 'SOQJLWB12A6701E7B3': 38,\n",
       " 'SOQQQMM12A6310DFCC': 39,\n",
       " 'SOQTPLM12B0B809575': 40,\n",
       " 'SOQZBYZ12A6701E7B0': 41,\n",
       " 'SOQZYQH12A8AE468E5': 42,\n",
       " 'SORAHAG12AB0182BD0': 43,\n",
       " 'SOREPNQ12A58A7B49E': 44,\n",
       " 'SORQVPO12AF72A690C': 45,\n",
       " 'SORRCNC12A8C13FDA9': 46,\n",
       " 'SORVLRC12A8151E078': 47,\n",
       " 'SORVYXQ12AB018C994': 48,\n",
       " 'SORWPCP12A8C13B9D8': 49,\n",
       " 'SORYCIK12AB018535E': 50,\n",
       " 'SOSACAB12AB01876E4': 51,\n",
       " 'SOSFSWB12AB018C99A': 52,\n",
       " 'SOSJSSU12A6D4F8F41': 53,\n",
       " 'SOSKFED12A8C1343AB': 54,\n",
       " 'SOSLQGG12A6D4F5045': 55,\n",
       " 'SOSNYHM12A67ADAFC8': 56,\n",
       " 'SOSVEAD12A8AE46FFA': 57,\n",
       " 'SOSYMSX12A6310DFE2': 58,\n",
       " 'SOTCDXN12AB01876A1': 59,\n",
       " 'SOTEFFR12A8C144765': 60,\n",
       " 'SOTEKMT12A67AD954E': 61,\n",
       " 'SOTEPSZ12AB018C99D': 62,\n",
       " 'SOTHQRU12A58A78698': 63,\n",
       " 'SOTIFJG12A6D4F786C': 64,\n",
       " 'SOTMKZF12AB0187412': 65,\n",
       " 'SOTODTI12A8C1402D3': 66,\n",
       " 'SOTSHYT12A8C142868': 67,\n",
       " 'SOTTGXB12A6701FA0B': 68,\n",
       " 'SOTVFIU12AC46878B7': 69,\n",
       " 'SOTWNDJ12A8C143984': 70,\n",
       " 'SOUFNSM12A58A77715': 71,\n",
       " 'SOUFPNI12A8C142D19': 72,\n",
       " 'SOUGCDK12AC95F075F': 73,\n",
       " 'SOUGLIK12A8C143DF4': 74,\n",
       " 'SOULBNJ12AB01851E9': 75,\n",
       " 'SOUNJIO12AB0181339': 76,\n",
       " 'SOUQQWB12AB01828AB': 77,\n",
       " 'SOUSAXA12AF72A73F5': 78,\n",
       " 'SOUUJMQ12A8C141D32': 79,\n",
       " 'SOUVTSM12AC468F6A7': 80,\n",
       " 'SOUZBUD12A8C13FD8E': 81,\n",
       " 'SOVALQH12AB0189114': 82,\n",
       " 'SOVCHUK12AB017F41F': 83,\n",
       " 'SOVDLZN12AB0185BEA': 84,\n",
       " 'SOVIZNF12AF72A710A': 85,\n",
       " 'SOVLJHG12A81C21AA0': 86,\n",
       " 'SOVMOCU12A8C140E82': 87,\n",
       " 'SOVNVRF12A8C14477B': 88,\n",
       " 'SOVPBLT12A6D4F5113': 89,\n",
       " 'SOVRTPN12AB0184F9E': 90,\n",
       " 'SOVRZIX12AAF3B2A32': 91,\n",
       " 'SOVUBST12AB018C9A4': 92,\n",
       " 'SOVWHPM12AB017DABB': 93,\n",
       " 'SOWGEWN12A6D4F789B': 94,\n",
       " 'SOWGHHQ12A67021878': 95,\n",
       " 'SOWKKGX12A6D4FCC01': 96,\n",
       " 'SOWOMMY127F8096DF9': 97,\n",
       " 'SOWQXHG12AB0189D1A': 98,\n",
       " 'SOWVNWB12A8C133171': 99,\n",
       " 'SOXAQJS12AB018CBF7': 100,\n",
       " 'SOXDIDW12B0B80954B': 101,\n",
       " 'SOXGXKY12A8C13A405': 102,\n",
       " 'SOXIIIM12A6D4F66C8': 103,\n",
       " 'SOXLKNJ12A58A7E09A': 104,\n",
       " 'SOXLWPN12A8C143667': 105,\n",
       " 'SOXPFLM12A8AE48C50': 106,\n",
       " 'SOXPZEZ12A8AE48AC9': 107,\n",
       " 'SOXTYBL12AB01887BB': 108,\n",
       " 'SOXXVSU12A8C133445': 109,\n",
       " 'SOYDTRQ12AF72A3D61': 110,\n",
       " 'SOYEQLD12AB017C713': 111,\n",
       " 'SOYEVUY12A8C145F58': 112,\n",
       " 'SOYEZKY12AB018909A': 113,\n",
       " 'SOYFQVR12AB018ACA5': 114,\n",
       " 'SOYIWVC12A8AE47F31': 115,\n",
       " 'SOYMIMI12AB0181E5C': 116,\n",
       " 'SOYNJCS12A67ADE35F': 117,\n",
       " 'SOYONCL12A8C13B9F7': 118,\n",
       " 'SOYRJTL12A67AD9551': 119,\n",
       " 'SOYSJUV12A8C139DCE': 120,\n",
       " 'SOYVSHP12A6702016E': 121,\n",
       " 'SOYYJMW12A6D4F8636': 122,\n",
       " 'SOZAPQT12A8C142821': 123,\n",
       " 'SOZGDUH12AF72A6DB2': 124,\n",
       " 'SOZPPYS12898B694CE': 125,\n",
       " 'SOZVCRW12A67ADA0B7': 126,\n",
       " 'SOZVUCT12A8C1424BE': 127,\n",
       " 'SOZXEZV12A6D4F737F': 128,\n",
       " 'SOZYBGN12A8C13A93C': 129,\n",
       " 'SOZYSDT12A8C13BFD7': 130,\n",
       " 'SOZZIOH12A67ADE300': 131,\n",
       " 'SOKVZHI12A58A7A13E': 132,\n",
       " 'SORBBFV12AB017D710': 133,\n",
       " 'SOSHJHA12AB0181410': 134,\n",
       " 'SOVPSKL12A670206B9': 135,\n",
       " 'SOYBHSI12A58A7D58B': 136,\n",
       " 'SOHTQAS12A6701C7BA': 137,\n",
       " 'SOIBLKQ12AB0183E85': 138,\n",
       " 'SOLEEUJ12A6701C787': 139,\n",
       " 'SOMFUWK12A6D4F8AFA': 140,\n",
       " 'SOPXKYD12A6D4FA876': 141,\n",
       " 'SOPZKGR12A6D4F3F3A': 142,\n",
       " 'SOQGVCS12AF72A078D': 143,\n",
       " 'SOQIQZU12A6D4FB8B5': 144,\n",
       " 'SOSQIHH12A8C13370B': 145,\n",
       " 'SOSQQGF12A6310F0FB': 146,\n",
       " 'SOTKYBW12A8C13C3EA': 147,\n",
       " 'SOTRQEJ12AF72A45D7': 148,\n",
       " 'SOUOPLF12AB017F40F': 149,\n",
       " 'SOURVJI12A58A7F353': 150,\n",
       " 'SOVGKPF12A8AE45594': 151,\n",
       " 'SOVTLQW12AB0186641': 152,\n",
       " 'SOWAACZ12A8C135AC1': 153,\n",
       " 'SOWFPLI12A6310DFA1': 154,\n",
       " 'SOWGDDU12AF72A03DA': 155,\n",
       " 'SOWKSFG12A8C13E535': 156,\n",
       " 'SOXGIWN12A6310E0D8': 157,\n",
       " 'SOXMGFH12A6701FF31': 158,\n",
       " 'SOXNYUA12AB017B49B': 159,\n",
       " 'SOXNZUH12AB018393F': 160,\n",
       " 'SOXQYSC12A6310E908': 161,\n",
       " 'SOXWYZP12AF72A42A6': 162,\n",
       " 'SOXZOMB12AB017DA15': 163,\n",
       " 'SOYCXUA12A8C133713': 164,\n",
       " 'SOZDACG12AB01853BB': 165,\n",
       " 'SOZIBZP12A6701C434': 166,\n",
       " 'SODCNJX12A6D4F93CB': 167,\n",
       " 'SORALYQ12A8151BA99': 168,\n",
       " 'SOVRMZU12AB017FE90': 169,\n",
       " 'SOWPASM12A8C142B88': 170,\n",
       " 'SOWSXLZ12AB017BD9A': 171,\n",
       " 'SOYAIPB12A8C143D84': 172,\n",
       " 'SOAXGDH12A8C13F8A1': 173,\n",
       " 'SOHFNKO12AB017C772': 174,\n",
       " 'SOILFUU12AB017C75F': 175,\n",
       " 'SOIMQAK12A67ADE98C': 176,\n",
       " 'SOODSPH12AB01819C3': 177,\n",
       " 'SOOWVNN12A8C140775': 178,\n",
       " 'SOPAYPV12AB017DB0C': 179,\n",
       " 'SOPCQRT12A8C13B15D': 180,\n",
       " 'SOPKPSQ12A58A7A5E4': 181,\n",
       " 'SOQHWMN12A6701E2D9': 182,\n",
       " 'SORGVYS12A8AE48882': 183,\n",
       " 'SOUCPBK12A58A7881A': 184,\n",
       " 'SOUSOOB12A8C13371F': 185,\n",
       " 'SOVMGXI12AF72A80B0': 186,\n",
       " 'SOWDLPO12A6D4F72BB': 187,\n",
       " 'SOWGCMN12A8C136E44': 188,\n",
       " 'SOWIMTL12A8C1386DC': 189,\n",
       " 'SOWRWMX12A8AE47FF8': 190,\n",
       " 'SOWVBDQ12A8C13503D': 191,\n",
       " 'SOXVVSM12A8C142224': 192,\n",
       " 'SOXYAUN12A58A7BE87': 193,\n",
       " 'SOYKFFK12A8C14391D': 194,\n",
       " 'SOAUWYT12A81C206F1': 195,\n",
       " 'SOBONKR12A58A7A7E0': 196,\n",
       " 'SOBOUPA12A6D4F81F1': 197,\n",
       " 'SODGJKH12AAA8C9487': 198,\n",
       " 'SODGVGW12AC9075A8D': 199,\n",
       " 'SODJWHY12A8C142CCE': 200,\n",
       " 'SOEBOWM12AB017F279': 201,\n",
       " 'SOFGJCW12AF72A812D': 202,\n",
       " 'SOFKABN12A8AE476C6': 203,\n",
       " 'SOGCWUH12AC90732B0': 204,\n",
       " 'SOGPBAW12A6D4F9F22': 205,\n",
       " 'SOGPNGN12A8C143969': 206,\n",
       " 'SOGSAYQ12AB018BA14': 207,\n",
       " 'SOGTQNI12AB0184A5C': 208,\n",
       " 'SOHTKMO12AB01843B0': 209,\n",
       " 'SOIMCDE12A6D4F8383': 210,\n",
       " 'SOISNSU12AC468C0D8': 211,\n",
       " 'SOJMUUU12A8C137A4F': 212,\n",
       " 'SOKUAGP12A8C133B94': 213,\n",
       " 'SOKUECJ12A6D4F6129': 214,\n",
       " 'SOKUPAO12AB018D576': 215,\n",
       " 'SOKZZGT12A67ADA4C3': 216,\n",
       " 'SOLFXKT12AB017E3E0': 217,\n",
       " 'SOLRBSH12AB018AE7B': 218,\n",
       " 'SOLRGVL12A8C143BC3': 219,\n",
       " 'SOLZEED12A6D4FA8C9': 220,\n",
       " 'SOMJFPG12A58A7DD95': 221,\n",
       " 'SOMOFOP12AB01825DD': 222,\n",
       " 'SOMYXWV12A8C14232E': 223,\n",
       " 'SONHVVE12AB018D038': 224,\n",
       " 'SONIQRE12AF72A2B02': 225,\n",
       " 'SONNSYV12A8C146BEC': 226,\n",
       " 'SONOYIB12A81C1F88C': 227,\n",
       " 'SOOFYTN12A6D4F9B35': 228,\n",
       " 'SOOGBWC12A8C140B96': 229,\n",
       " 'SOONUTJ12A6701D7B4': 230,\n",
       " 'SOOWPBJ12A8C137FB4': 231,\n",
       " 'SOPDRWC12A8C141DDE': 232,\n",
       " 'SOPEOGA12AB017B694': 233,\n",
       " 'SOPFVER12AB0180FEF': 234,\n",
       " 'SOPGCOH12A8C139789': 235,\n",
       " 'SOPPROJ12AB0184E18': 236,\n",
       " 'SOPUCYA12A8C13A694': 237,\n",
       " 'SOPVQLJ12A67AE2281': 238,\n",
       " 'SOQNOAF12A8151AB86': 239,\n",
       " 'SOQTFOR12A6D4F612A': 240,\n",
       " 'SOQWSHS12A6701C576': 241,\n",
       " 'SOREBOB12A6D4F7986': 242,\n",
       " 'SOSCIZP12AB0181D2F': 243,\n",
       " 'SOSHVEI12AF729AF6B': 244,\n",
       " 'SOSINBC12A67ADAEF6': 245,\n",
       " 'SOSNTSY12AF72A7B43': 246,\n",
       " 'SOSUUQF12A6D4F8B2A': 247,\n",
       " 'SOSVDRD12A67ADAEF1': 248,\n",
       " 'SOSVPIE12A6D4FA873': 249,\n",
       " 'SOSXLTC12AF72A7F54': 250,\n",
       " 'SOTCMDJ12A6D4F8528': 251,\n",
       " 'SOTKMXA12A6D4F672F': 252,\n",
       " 'SOTVLQY12A58A798C2': 253,\n",
       " 'SOTWSXL12A8C143349': 254,\n",
       " 'SOTZION12A6D4FB477': 255,\n",
       " 'SOUCBEB12A6310E1F9': 256,\n",
       " 'SOUCKDH12A8C138FF5': 257,\n",
       " 'SOUDLVN12AAFF43658': 258,\n",
       " 'SOUFTBI12AB0183F65': 259,\n",
       " 'SOUJVIT12A8C1451C1': 260,\n",
       " 'SOUKJBT12A6701C4D6': 261,\n",
       " 'SOUKMKR12A8C141925': 262,\n",
       " 'SOULTKQ12AB018A183': 263,\n",
       " 'SOUSMXX12AB0185C24': 264,\n",
       " 'SOUSZSW12AB01800C2': 265,\n",
       " 'SOVBRCP12A6701D7B5': 266,\n",
       " 'SOVDSJC12A58A7A271': 267,\n",
       " 'SOVDYZE12A58A7AA62': 268,\n",
       " 'SOVWADY12AB0189C63': 269,\n",
       " 'SOWBHRF12A8C137AB2': 270,\n",
       " 'SOWCKVR12A8C142411': 271,\n",
       " 'SOWGXOP12A6701E93A': 272,\n",
       " 'SOWNIUS12A8C142815': 273,\n",
       " 'SOWOAXK12A6310D81F': 274,\n",
       " 'SOWRMTT12A8C137064': 275,\n",
       " 'SOWSHHE12AF729F422': 276,\n",
       " 'SOWYYUQ12A6701D68D': 277,\n",
       " 'SOXBZEQ12A8C14307F': 278,\n",
       " 'SOXDPEP12AB0180E1E': 279,\n",
       " 'SOXFPND12AB017C9D1': 280,\n",
       " 'SOXGQEM12AB0181D35': 281,\n",
       " 'SOXGTRO12A8C143454': 282,\n",
       " 'SOXKFRI12A8C137A5F': 283,\n",
       " 'SOXLRDB12A81C21739': 284,\n",
       " 'SOXNZOW12AB017F756': 285,\n",
       " 'SOXQROF12AB0186B1D': 286,\n",
       " 'SOYFMNU12AB0181435': 287,\n",
       " 'SOYHHCO12AB01891DA': 288,\n",
       " 'SOYJPNY12AB01869CC': 289,\n",
       " 'SOYKNUX12A58A7B1C6': 290,\n",
       " 'SOYOGWU12A8AE481A6': 291,\n",
       " 'SOYPRBR12A8C14396C': 292,\n",
       " 'SOYQQAC12A6D4FD59E': 293,\n",
       " 'SOYRAHL12A6310D821': 294,\n",
       " 'SOYVFTH12A67020868': 295,\n",
       " 'SOYWTUB12A8C13B429': 296,\n",
       " 'SOZARJQ12A6D4F66CE': 297,\n",
       " 'SOZBZFF12A6310F12D': 298,\n",
       " 'SOZHUUI12A6701D7B6': 299,\n",
       " 'SOZOIUU12A67ADFA39': 300,\n",
       " 'SOZSZTY12A8C13B693': 301,\n",
       " 'SOZVSSP12AB01819DE': 302,\n",
       " 'SOZVVRE12A8C143150': 303,\n",
       " 'SOEQJBS12A8AE475A4': 304,\n",
       " 'SOFRCGW12A81C21EA6': 305,\n",
       " 'SOFVZRE12A8C139783': 306,\n",
       " 'SOGTDJQ12A8C13324F': 307,\n",
       " 'SOKMHKY12AF72AB079': 308,\n",
       " 'SOLLNTU12A6701CFDC': 309,\n",
       " 'SOLRGNF12AB0187CF4': 310,\n",
       " 'SOLWZVR12AB01849C6': 311,\n",
       " 'SOMMUKQ12AB01801A5': 312,\n",
       " 'SOOHCUB12A58A7AD2C': 313,\n",
       " 'SOOJJCT12A6310E1C0': 314,\n",
       " 'SOOLYZQ12A6D4FA5B7': 315,\n",
       " 'SOOXLIG12AB0185803': 316,\n",
       " 'SOPSYOY12A8C142E0B': 317,\n",
       " 'SOPTLQL12AB018D56F': 318,\n",
       " 'SOQKNEO12A58A78EE7': 319,\n",
       " 'SOQTHZW12A8C1400F8': 320,\n",
       " 'SORZCTH12A6D4FB0BD': 321,\n",
       " 'SOSROFB12AAF3B4C5D': 322,\n",
       " 'SOTVMLE12AB018168E': 323,\n",
       " 'SOUSOKG12A58A7AC15': 324,\n",
       " 'SOVVENS12A8C144DB5': 325,\n",
       " 'SOVYTXK12AB01800F5': 326,\n",
       " 'SOWEJXA12A6701C574': 327,\n",
       " 'SOWRTJD12A8C132704': 328,\n",
       " 'SOXACZF12A6D4FB153': 329,\n",
       " 'SOYGHOJ12A6701FFBA': 330,\n",
       " 'SOYPWKK12A8C136494': 331,\n",
       " 'SOMZVGZ12A8C140EFF': 332,\n",
       " 'SONJILQ12A67020456': 333,\n",
       " 'SONNNEH12AB01827DE': 334,\n",
       " 'SOOXRJG12A8C13773E': 335,\n",
       " 'SOPJLFV12A6701C797': 336,\n",
       " 'SOPLAHV12A8C13D110': 337,\n",
       " 'SORKFPY12A8AE46AFB': 338,\n",
       " 'SOSBKKN12A8C1384B4': 339,\n",
       " 'SOTNHIP12AB0183131': 340,\n",
       " 'SOWFIFP12A8C13A9EE': 341,\n",
       " 'SOWQMMX12AB017DBE2': 342,\n",
       " 'SOXBCZH12A67ADAD77': 343,\n",
       " 'SOXLSBV12AB018397A': 344,\n",
       " 'SOXTBGF12A6D4FB49C': 345,\n",
       " 'SOFCPOU12A8C13BF40': 346,\n",
       " 'SOHFJAQ12AB017E4AF': 347,\n",
       " 'SOHNOOC12A8C13BF35': 348,\n",
       " 'SOLRDEI12A8C13AAA2': 349,\n",
       " 'SOLTSGU12A8C13BFE5': 350,\n",
       " 'SOMCAFM12A58A7B024': 351,\n",
       " 'SONQCXC12A6D4F6A37': 352,\n",
       " 'SOOEEPE12A8AE459A4': 353,\n",
       " 'SOOGNOZ12AAF3B2936': 354,\n",
       " 'SOOXJDU12A8AE47ECB': 355,\n",
       " 'SORFVMQ12AB0184135': 356,\n",
       " 'SORJVDO12AF72A1970': 357,\n",
       " 'SORVBEQ12A8C133D6B': 358,\n",
       " 'SOSBNIU12AB017CFEB': 359,\n",
       " 'SOSELMV12A6D4FCF5A': 360,\n",
       " 'SOSJDQJ12A8C13D4A9': 361,\n",
       " 'SOSLQQJ12AB017BDCC': 362,\n",
       " 'SOSRCCU12A67ADA089': 363,\n",
       " 'SOSVQNK12AC468D6BE': 364,\n",
       " 'SOTGZIH12A8C1428A5': 365,\n",
       " 'SOTUILE12A6D4FA444': 366,\n",
       " 'SOWGIBZ12A8C136A2E': 367,\n",
       " 'SOWIYOP12A8C140E73': 368,\n",
       " 'SOWMGHQ12A6D4F914D': 369,\n",
       " 'SOWNIWL12AB017B720': 370,\n",
       " 'SOWPRYI12A58A7B51A': 371,\n",
       " 'SOWWCNJ12A81C1FFA5': 372,\n",
       " 'SOXCZGH12A8C13C4FE': 373,\n",
       " 'SOXERNH12A67AD8642': 374,\n",
       " 'SOXKOIY12A8C13C1EA': 375,\n",
       " 'SOYEWFR12AB0189AB6': 376,\n",
       " 'SOYJJRX12A8C137A0F': 377,\n",
       " 'SOYZKVX12A8C13A181': 378,\n",
       " 'SOZHJKI12A81C2248F': 379,\n",
       " 'SOFLJQZ12A6D4FADA6': 380,\n",
       " 'SOOLULU12A6701FBC4': 381,\n",
       " 'SORMGEO12A8C14406D': 382,\n",
       " 'SOSRIHB12A8C13608B': 383,\n",
       " 'SOTNEEA12A6D4F7F8D': 384,\n",
       " 'SOUGAYN12A6D4F6E90': 385,\n",
       " 'SOUUZPU12A6701FB90': 386,\n",
       " 'SOUVUHC12A67020E3B': 387,\n",
       " 'SOVJTTZ12AB017F48F': 388,\n",
       " 'SOVMKIC12AF72A05CC': 389,\n",
       " 'SOWBNGK12A8C143932': 390,\n",
       " 'SOWQOMG12A6701D1F3': 391,\n",
       " 'SOWXDVT12B0B80BFA3': 392,\n",
       " 'SOXELPB12A8AE46000': 393,\n",
       " 'SOXHIDK12A58A7CFB3': 394,\n",
       " 'SOYWBPL12B0B80BD74': 395,\n",
       " 'SOZBZSY12A6D4FA404': 396,\n",
       " 'SOZORGY12A8C140382': 397,\n",
       " 'SOZXBIS12A8AE44A2E': 398,\n",
       " 'SOHNVHC12A6D4F95AB': 399,\n",
       " 'SOLJWIQ12A6D4FA875': 400,\n",
       " 'SOMWCVL12AF729E81A': 401,\n",
       " 'SONQEYS12AF72AABC9': 402,\n",
       " 'SONQJCU12A8C144398': 403,\n",
       " 'SOOSDMO12A6D4F80F9': 404,\n",
       " 'SOQLFVE12AB017E74E': 405,\n",
       " 'SORWEEW12A58A7A935': 406,\n",
       " 'SOSXPFU12AB017FE27': 407,\n",
       " 'SOTGHQR12A8C1406C5': 408,\n",
       " 'SOTIDKX12A6D4FA7EA': 409,\n",
       " 'SOTSPVI12A6D4FA446': 410,\n",
       " 'SOUDGEV12A8C135FC9': 411,\n",
       " 'SOUDZSZ12A6D4FA238': 412,\n",
       " 'SOUXIXD12AF72A1592': 413,\n",
       " 'SOVVRDZ12A6701C577': 414,\n",
       " 'SOVXBOT12A8C136816': 415,\n",
       " 'SOWDRRZ12A8C13AE89': 416,\n",
       " 'SOXCDAP12A8C1371AF': 417,\n",
       " 'SOXLJXH12A8C13D903': 418,\n",
       " 'SOYCHDB12A8C13F2C8': 419,\n",
       " 'SOZAZZK12A6701F98D': 420,\n",
       " 'SOZUPDR12A8C137FB6': 421,\n",
       " 'SOZYDZR12A8C13F4F0': 422,\n",
       " 'SOERYLG12A6701F07F': 423,\n",
       " 'SOJSTYO12A8C13F200': 424,\n",
       " 'SOKUTUM12A6701D9CD': 425,\n",
       " 'SOLTIVF12AAFF43797': 426,\n",
       " 'SOMYECL12A6701D9C8': 427,\n",
       " 'SOOABBO12A6701DFDA': 428,\n",
       " 'SOQGOPT12AAF3B2B27': 429,\n",
       " 'SOSPXWA12AB0181875': 430,\n",
       " 'SOSRERB12A8C139735': 431,\n",
       " 'SOTJTQI12A6D4F75A2': 432,\n",
       " 'SOUMOMJ12A6701DFDC': 433,\n",
       " 'SOUTGUB12AB017DC5B': 434,\n",
       " 'SOUZDWT12B0B80BC62': 435,\n",
       " 'SOVFFSK12A6BD55C96': 436,\n",
       " 'SOVGLTY12AF72A39CD': 437,\n",
       " 'SOVMWUC12A8C13750B': 438,\n",
       " 'SOWEWRL12A58A7961F': 439,\n",
       " 'SOXDQPZ12A8C13F4FC': 440,\n",
       " 'SOYDOZE12A6701FC22': 441,\n",
       " 'SOYHEPA12A8C13097F': 442,\n",
       " 'SOYIJIL12A6701F1C1': 443,\n",
       " 'SOOECND12A8C13A0EA': 444,\n",
       " 'SORRYFP12A8C13A08D': 445,\n",
       " 'SOVIKOY12AB018627D': 446,\n",
       " 'SOYGQGR12AF72ABAB8': 447,\n",
       " 'SOEPZQS12A8C1436C7': 448,\n",
       " 'SOMLYJD12A58A7B155': 449,\n",
       " 'SONZWDK12A6701F62B': 450,\n",
       " 'SOOAVGC12AB01821EC': 451,\n",
       " 'SOPKEIV12AB018220D': 452,\n",
       " 'SOQLFRX12A6D4F9200': 453,\n",
       " 'SOSYHME12A8C135DD8': 454,\n",
       " 'SOSYVNJ12AB01829E8': 455,\n",
       " 'SOUCHPA12AB0184B1A': 456,\n",
       " 'SOUEGBF12AB017EFD5': 457,\n",
       " 'SOUGMXP12AB017C76C': 458,\n",
       " 'SOUOCRG12A67AE0E17': 459,\n",
       " 'SOUVGJL12AB017FC35': 460,\n",
       " 'SOVEUVC12A6310EAF1': 461,\n",
       " 'SOWNRRW12A58A801BA': 462,\n",
       " 'SOXZUAV12A6310F21A': 463,\n",
       " 'SOZCDWG12A6D4F81E1': 464,\n",
       " 'SOZMEWR12A6701EBD9': 465,\n",
       " 'SOZSFWF12A6D4F93D5': 466,\n",
       " 'SOIIOUS12A8AE47E20': 467,\n",
       " 'SOIZAZL12A6701C53B': 468,\n",
       " 'SOMGVYU12A8C1314FF': 469,\n",
       " 'SOMNXML12A6D4F8386': 470,\n",
       " 'SOOBGSW12A6D4F9D51': 471,\n",
       " 'SOPNLBX12A8C1377D4': 472,\n",
       " 'SOPSOHT12A67AE0235': 473,\n",
       " 'SOPWZGK12A67020744': 474,\n",
       " 'SOQGJZA12A8C1367AE': 475,\n",
       " 'SOQPCVN12AF729FB85': 476,\n",
       " 'SORJICW12A8C13640D': 477,\n",
       " 'SOSTTPA12A8AE47622': 478,\n",
       " 'SOTEGWG12AB01897AC': 479,\n",
       " 'SOTUCYL12A8C14487F': 480,\n",
       " 'SOTWCDE12AB018909C': 481,\n",
       " 'SOUFWEW12AB0180EB7': 482,\n",
       " 'SOVOOSP12A6310F1AC': 483,\n",
       " 'SOWBTPS12A6D4FA5BE': 484,\n",
       " 'SOWPLVJ12AB0183586': 485,\n",
       " 'SOXAAFS12A8C14041D': 486,\n",
       " 'SOYGKNI12AB0187E6E': 487,\n",
       " 'SOEYVHS12AB0181D31': 488,\n",
       " 'SOGWJEY12AC9618862': 489,\n",
       " 'SOIDDNJ12AC9071B90': 490,\n",
       " 'SOJGZXL12A6D4F2980': 491,\n",
       " 'SOLCKAS12A8C14242A': 492,\n",
       " 'SOLGLUC12AB018A8FA': 493,\n",
       " 'SOLRPJX12A58A79808': 494,\n",
       " 'SOLWAHM12AB018EBC8': 495,\n",
       " 'SOMEUED12A6701DBEA': 496,\n",
       " 'SONHWUN12AC468C014': 497,\n",
       " 'SOODHLO12AF72A1980': 498,\n",
       " 'SOOLWEJ12AB0186DA4': 499,\n",
       " 'SOOTKWZ12AB0181082': 500,\n",
       " 'SOOXLND12A6D4FE36E': 501,\n",
       " 'SOTASGN12AC9075A8F': 502,\n",
       " 'SOTVJEN12A8C13B064': 503,\n",
       " 'SOUVDUK12A8AE489A3': 504,\n",
       " 'SOVHKJL12AB017E2B2': 505,\n",
       " 'SOVTQLS12A6D4F8350': 506,\n",
       " 'SOWCBKV12AC90732A6': 507,\n",
       " 'SOXCCPU12A58A7BF1E': 508,\n",
       " 'SOXLOQG12AF72A2D55': 509,\n",
       " 'SOXMOQF12A6701FB8B': 510,\n",
       " 'SOZTCOW12A8C134269': 511,\n",
       " 'SOIPYPB12A8C1360D4': 512,\n",
       " 'SONGIPI12A8AE46162': 513,\n",
       " 'SONVPTP12A6D4F7A34': 514,\n",
       " 'SOPKPFW12A6D4F84BC': 515,\n",
       " 'SOSLZXV12A8C1354C9': 516,\n",
       " 'SOSXVAS12A6310F1AD': 517,\n",
       " 'SOTCWRK12AB017E47D': 518,\n",
       " 'SOVFBUL12A58A7B498': 519,\n",
       " 'SOVHFMK12A679AE565': 520,\n",
       " 'SOWEBRA12A6701F115': 521,\n",
       " 'SOWKRRE12A6702073E': 522,\n",
       " 'SOWKYIJ12AB017B0AA': 523,\n",
       " 'SOWUTFF12A8C138AB2': 524,\n",
       " 'SOXILLO12A6310F1B6': 525,\n",
       " 'SOXOZIX12AF72A4EA0': 526,\n",
       " 'SOYALKY12A8C137576': 527,\n",
       " 'SOYIBFQ12A6701C628': 528,\n",
       " 'SOZBAAH12A6D4F959F': 529,\n",
       " 'SOMMKEW12A58A80F00': 530,\n",
       " 'SOQQAAQ12A67ADE34D': 531,\n",
       " 'SOWKGCO12AC4687E42': 532,\n",
       " 'SOJHCOH12A8AE45F4F': 533,\n",
       " 'SOLARJV12AB018306B': 534,\n",
       " 'SOMMONH12A6D4F41CD': 535,\n",
       " 'SONIMNU12B0B8092AB': 536,\n",
       " 'SORKDWS12A6701E6D9': 537,\n",
       " 'SOSCDWE12AB01823C4': 538,\n",
       " 'SOSGBJB12A6D4FCDEC': 539,\n",
       " 'SOTDKEJ12AB0187AAA': 540,\n",
       " 'SOTORXA12A58A79338': 541,\n",
       " 'SOTSRUQ12A81C22359': 542,\n",
       " 'SOVBJIV12A81C22366': 543,\n",
       " 'SOVHVBJ12A58A7AB0A': 544,\n",
       " 'SOVSGXX12A58A7F991': 545,\n",
       " 'SOWSSRH12A58A7CE5D': 546,\n",
       " 'SOWTCET12A58A7A60E': 547,\n",
       " 'SOXFYTY127E9433E7D': 548,\n",
       " 'SOXHYWX12A8C142CE8': 549,\n",
       " 'SOXPDDQ12A58A76829': 550,\n",
       " 'SOXZCIH12A8C1425F0': 551,\n",
       " 'SOHYSXA12AB0186704': 552,\n",
       " 'SOIROON12A6701E0B8': 553,\n",
       " 'SOJTLHS12A8C13F633': 554,\n",
       " 'SOLOFYI12A8C145F8D': 555,\n",
       " 'SONWUZV12AB0180BAD': 556,\n",
       " 'SOOLPFK12A58A7BDE3': 557,\n",
       " 'SOQWYAQ12A6D4FB9A3': 558,\n",
       " 'SORNWVM12AF72A14ED': 559,\n",
       " 'SORPVUD12A67020454': 560,\n",
       " 'SOSXSMM12B0B808B45': 561,\n",
       " 'SOSYOHI12A8C144584': 562,\n",
       " 'SOUFWFG12AC9072C7E': 563,\n",
       " 'SOUKXIN12A8C133C7F': 564,\n",
       " 'SOUOEMP12A8C13866E': 565,\n",
       " 'SOVXCNA12A58A7881A': 566,\n",
       " 'SOWKVVW12A8AE45E8C': 567,\n",
       " 'SOXRSDX12A67ADA057': 568,\n",
       " 'SOZXKIA12A6D4F861C': 569,\n",
       " 'SONTQUO12A6D4F7D8B': 570,\n",
       " 'SORTDSD12A6D4F798B': 571,\n",
       " 'SOTXDCY12AF729A39B': 572,\n",
       " 'SOWTYVO12AB0180BDA': 573,\n",
       " 'SOWUZVU12A6D4F914D': 574,\n",
       " 'SOSYMWV12AB0184F86': 575,\n",
       " 'SOVWPNQ12A8C132A63': 576,\n",
       " 'SOKRAMY12A8C140804': 577,\n",
       " 'SOTMLOE12A8C133F15': 578,\n",
       " 'SOWYFFH12AAF3B4C65': 579,\n",
       " 'SOITRTA12A6D4F8261': 580,\n",
       " 'SOKKKZW12A6D4F7F88': 581,\n",
       " 'SOTRDVJ12A8C13975E': 582,\n",
       " 'SOVJJQI12A6D4F5910': 583,\n",
       " 'SOZDYMX12A58A7D443': 584,\n",
       " 'SOFEGST12A58A7D682': 585,\n",
       " 'SONAZWN12A8151C957': 586,\n",
       " 'SONEWAX12AB018DD3F': 587,\n",
       " 'SOPQQNK12A8C13BF46': 588,\n",
       " 'SOQBMFK12A8C13835B': 589,\n",
       " 'SOQWZAB12AB017C6F7': 590,\n",
       " 'SORJBJB12A8C13E711': 591,\n",
       " 'SORWLTW12A670208FA': 592,\n",
       " 'SOSJFDH12A8C143096': 593,\n",
       " 'SOSZJFV12AB01878CB': 594,\n",
       " 'SOTCDXR12A679D7E5E': 595,\n",
       " 'SOTHABI12A58A7DACB': 596,\n",
       " 'SOTRSFZ12A8C142BF6': 597,\n",
       " 'SOUDBWL12A6D4F8155': 598,\n",
       " 'SOUYMPF12A58A7C78A': 599,\n",
       " 'SOVHYVB12A3F1EC277': 600,\n",
       " 'SOVJHCB12A8AE4636E': 601,\n",
       " 'SOVPDKK12A8C138DA5': 602,\n",
       " 'SOVYIYI12A8C138D88': 603,\n",
       " 'SOWLFNL12AB017DB20': 604,\n",
       " 'SOWSCPW12AB0182803': 605,\n",
       " 'SOXEUDZ12A8C13145B': 606,\n",
       " 'SOXEZLY12A8C137AB0': 607,\n",
       " 'SOXFXDH12A8C13326E': 608,\n",
       " 'SOYCXBA12A6701E35B': 609,\n",
       " 'SOYDTIW12A67ADAFC9': 610,\n",
       " 'SOYELXR12A8C14153A': 611,\n",
       " 'SOYIOZB12A58A797FC': 612,\n",
       " 'SOYOKCE12A58A79862': 613,\n",
       " 'SOZCWQA12A6701C798': 614,\n",
       " 'SOJKQSF12A6D4F5EE9': 615,\n",
       " 'SOJYBJZ12AB01801D0': 616,\n",
       " 'SOLWHSJ12A67AE227B': 617,\n",
       " 'SOOYDAZ12A58A7AE08': 618,\n",
       " 'SOTJDDY12AB017DC5B': 619,\n",
       " 'SOUNZHU12A8AE47481': 620,\n",
       " 'SOWEUOO12A6D4F6D0C': 621,\n",
       " 'SOWKRSR12A8C13CA37': 622,\n",
       " 'SOWRREB12A6D4FA7CB': 623,\n",
       " 'SOYGHUM12AB018139C': 624,\n",
       " 'SOOCKPO12A67021D10': 625,\n",
       " 'SOSFPMR12A8C13D44A': 626,\n",
       " 'SOSJRJP12A6D4F826F': 627,\n",
       " 'SOXJHPY12AF72A5227': 628,\n",
       " 'SOHZPIK12A58A7CCAE': 629,\n",
       " 'SOIZFTE12AB0186842': 630,\n",
       " 'SOWEHOM12A6BD4E09E': 631,\n",
       " 'SOWKQYL12AB0183B15': 632,\n",
       " 'SOXEYIE12AB0180212': 633,\n",
       " 'SOZKNSB12A8C140F11': 634,\n",
       " 'SONIAKP12A8C130514': 635,\n",
       " 'SOPTPWD12A6D4FBD4E': 636,\n",
       " 'SOPUELG12A6701D215': 637,\n",
       " 'SOQLUTQ12A8AE48037': 638,\n",
       " 'SOQOSMU12A8C138957': 639,\n",
       " 'SORWLJM12A6D4F9C0C': 640,\n",
       " 'SOSNMJN12A58A7A649': 641,\n",
       " 'SOSNOSA12A67ADA05B': 642,\n",
       " 'SOTFIPT12A6701F2FA': 643,\n",
       " 'SOUBXSF12A6701D23C': 644,\n",
       " 'SOUCMUI12AB018C0C6': 645,\n",
       " 'SOUIYDY12A8C141517': 646,\n",
       " 'SOULHTS12A6D4FAE9C': 647,\n",
       " 'SOUPMLF12A6701EAFE': 648,\n",
       " 'SOVQJRY12A81C210C0': 649,\n",
       " 'SOVWBYM12A6D4F8A22': 650,\n",
       " 'SOXCEYU12A6D4F3E70': 651,\n",
       " 'SOXEGBZ12A679AE53D': 652,\n",
       " 'SOXEOLH12A6D4F9D37': 653,\n",
       " 'SOXJYJM12A6310D7C1': 654,\n",
       " 'SOXKDFJ12A6D4FA8F9': 655,\n",
       " 'SOXLDLO12AB0186373': 656,\n",
       " 'SOYSADG12A8AE47F2C': 657,\n",
       " 'SOZDGEW12A8C13E748': 658,\n",
       " 'SOZUVYE12AB017CA2D': 659,\n",
       " 'SOIEBXT12A8C1341E1': 660,\n",
       " 'SOZQRSR12A6701E2F7': 661,\n",
       " 'SOSUZFA12A8C13C04A': 662,\n",
       " 'SOKYHYL12A8C13D79D': 663,\n",
       " 'SOMWTWK12AB01860CD': 664,\n",
       " 'SORUFVF12AB018230B': 665,\n",
       " 'SOSUWJE12AB0184567': 666,\n",
       " 'SOUKTVI12A8C13BF74': 667,\n",
       " 'SOVAUWH12AB01857EA': 668,\n",
       " 'SOXJLLK12A8C139E3D': 669,\n",
       " 'SOZCKAG12AB0182BA1': 670,\n",
       " 'SOZPLKR12A6D4F8421': 671,\n",
       " 'SOSWDMO12A8AE45996': 672,\n",
       " 'SOWLCQY12A6D4F84CF': 673,\n",
       " 'SOXKGUD12A58A7C687': 674,\n",
       " 'SOYHTAT12A81C23955': 675,\n",
       " 'SOZEBLF12A6D4F8259': 676,\n",
       " 'SORVEKH12A6D4F6CF2': 677,\n",
       " 'SOWPAXV12A67ADA046': 678,\n",
       " 'SOSEUUV12A6701E93C': 679,\n",
       " 'SOVMCAR12AF72A1268': 680,\n",
       " 'SOWKXQS12A8C1343A6': 681,\n",
       " 'SOYIZSN12A6701E0BB': 682,\n",
       " 'SOUVLRM12A8C141A0E': 683,\n",
       " 'SOZFYTZ12AB018565D': 684,\n",
       " 'SOHRQFL12A6D4F3C8A': 685,\n",
       " 'SOKOXWU12AF72AD1BC': 686,\n",
       " 'SONEJIJ12AB0185727': 687,\n",
       " 'SOPIEIJ12A6D4F8F81': 688,\n",
       " 'SOMHEVM12A58A80951': 689,\n",
       " 'SOSZESM12AB01810BF': 690,\n",
       " 'SOVOHCH12AB0184593': 691,\n",
       " 'SOVRGXP12AB017D2B9': 692,\n",
       " 'SOWQWFF12A81C214F9': 693,\n",
       " 'SOWSPUS12AC468BEE3': 694,\n",
       " 'SOJEVHC12A8C13C3E5': 695,\n",
       " 'SONPLUD12A8C13BF4B': 696,\n",
       " 'SOQXNGV12A6701E312': 697,\n",
       " 'SORYLNP12A8C13C3E7': 698,\n",
       " 'SOTTGRP12A67ADE985': 699,\n",
       " 'SOQCGHN12AB0181246': 700,\n",
       " 'SOUGOHW12AB018AEA3': 701,\n",
       " 'SOZNLBZ12A6D4F639E': 702,\n",
       " 'SOLGPOU12A58A7EA20': 703,\n",
       " 'SOMXDFJ12AB0183B34': 704,\n",
       " 'SONMBPQ12A6D4F95A3': 705,\n",
       " 'SONMOVN12A8C13C0C9': 706,\n",
       " 'SOOSADY12A6701F119': 707,\n",
       " 'SOVVBPK12A58A810CA': 708,\n",
       " 'SOXHPVI12A6D4F903A': 709,\n",
       " 'SOXQWUS12A58A7B236': 710,\n",
       " 'SOYLDJC12A6701E2FF': 711,\n",
       " 'SOLXXZI12A8AE4733A': 712,\n",
       " 'SOMCMKG12A8C1347BF': 713,\n",
       " 'SOPREHY12AB01815F9': 714,\n",
       " 'SOTUARP12A8C13CB54': 715,\n",
       " 'SOYABSZ12A81C1FEAC': 716,\n",
       " 'SOYJDRA12AB017F30D': 717,\n",
       " 'SOZEBAZ12AF72A80C8': 718,\n",
       " 'SOZEETS12AC9071BD3': 719,\n",
       " 'SORGRVL12A6310F105': 720,\n",
       " 'SOKTJXL12A8C13C90B': 721,\n",
       " 'SOVFNKP12A81C2177F': 722,\n",
       " 'SOVHPUT12A81C22A56': 723,\n",
       " 'SOXZTLV12A6701FFDD': 724,\n",
       " 'SOZOWON12A67ADA091': 725,\n",
       " 'SOXKXJG12A6D4FA272': 726,\n",
       " 'SORKVID12A6D4FC6D2': 727,\n",
       " 'SOTTTEQ12B0B80CA01': 728,\n",
       " 'SOVMSAW12A6D4F95A4': 729,\n",
       " 'SOWDKXZ12A81C22377': 730,\n",
       " 'SOWGZIE12A6D4FC6F2': 731,\n",
       " 'SOWQJUV12A6701FA45': 732,\n",
       " 'SOWONPQ12A8BED02A8': 733,\n",
       " 'SOMORYX12B0B80908A': 734,\n",
       " 'SONJNEQ12A6D4F9EB6': 735,\n",
       " 'SOQJNKS12A6D4FBF52': 736,\n",
       " 'SOUNNWW12AB018795D': 737,\n",
       " 'SOXUYUZ12A8C13A67E': 738,\n",
       " 'SOYTDBL12A6D4F8148': 739,\n",
       " 'SOZQLLE12A6D4F7170': 740,\n",
       " 'SOZVVMJ12A58A7C548': 741,\n",
       " 'SOSNJIT12A8159E8DB': 742,\n",
       " 'SOTLHUV12A6D4FC541': 743,\n",
       " 'SOZDTJE12A6701F2FE': 744,\n",
       " 'SOSSVAH12A6D4F9681': 745,\n",
       " 'SOWNVIV12AB0184846': 746,\n",
       " 'SOSKDTM12A6701C795': 747,\n",
       " 'SOZCCEU12A8C13D1EA': 748,\n",
       " 'SOZRIFX12A8C142691': 749,\n",
       " 'SOPABZM12A6D4FC668': 750,\n",
       " 'SOTKNTF12A8C144A0D': 751,\n",
       " 'SOUXNNU12A67020A48': 752,\n",
       " 'SOVZHYS12A8C14663F': 753,\n",
       " 'SOWBYZF12A6D4F9424': 754,\n",
       " 'SOXAHKA12AF72A5A65': 755,\n",
       " 'SOQCNFV12A6701D92A': 756,\n",
       " 'SOTWWEV12AC9074E6F': 757,\n",
       " 'SOUBZPQ12A8C13629D': 758,\n",
       " 'SOVYNVS12AC3DF64AB': 759,\n",
       " 'SOXHYVQ12AB0187949': 760,\n",
       " 'SOPLUOT12A6D4F7AC3': 761,\n",
       " 'SOSSUUS12A6701EA3C': 762,\n",
       " 'SOTHRRH12A8C13DCBA': 763,\n",
       " 'SOTJQZN12AF72AA288': 764,\n",
       " 'SOUWEJS12AB01868A4': 765,\n",
       " 'SOWKUZM12A67AE0D37': 766,\n",
       " 'SOXCUHM12B0B8092BB': 767,\n",
       " 'SOXDHVL12A6D4FBBE7': 768,\n",
       " 'SOXZMNC12A8C135DD5': 769,\n",
       " 'SOYIEGB12A6D4F8C07': 770,\n",
       " 'SOYLLGK12A81C217A1': 771,\n",
       " 'SOYYIMV12A8C13E4ED': 772,\n",
       " 'SOZJHUF12A8C13E642': 773,\n",
       " 'SOWNVJP12A58A761AA': 774,\n",
       " 'SOWPCTZ12A6310D890': 775,\n",
       " 'SOXNOYN12A6D4FB4B4': 776,\n",
       " 'SOYIYFF12A6701D22F': 777,\n",
       " 'SOYZOUY12AAF3B5B94': 778,\n",
       " 'SOYYFLV12A58A7A88F': 779,\n",
       " 'SOVPAJA12A58A77B15': 780,\n",
       " 'SOYDHXP12AB01849D4': 781,\n",
       " 'SOQJHUW12AB0188A24': 782,\n",
       " 'SOXPSGF12AB0187589': 783,\n",
       " 'SOQQGBB12A6D4FCE33': 784,\n",
       " 'SOZVMYF12A8C132646': 785,\n",
       " 'SOXTTHY12A8C137072': 786,\n",
       " 'SOXFMAQ12A6D4F91E0': 787,\n",
       " 'SOYYCTP12AB017E29C': 788,\n",
       " 'SOPTLTT12A58A7938D': 789,\n",
       " 'SOYUDDS12A6D4F7BD6': 790,\n",
       " 'SOUODFE12A58A80347': 791,\n",
       " 'SOUSQCN12A8C133302': 792,\n",
       " 'SOVEFXA12A58A7942A': 793,\n",
       " 'SOVOKGC12A58A7DF6B': 794,\n",
       " 'SOZBDZN12A8C130C7B': 795,\n",
       " 'SOXCBEF12A8C146AFE': 796,\n",
       " 'SOLZOBD12AB0185720': 797,\n",
       " 'SOYYKLS12A8C134802': 798,\n",
       " 'SOZZTNF12A8C139916': 799}"
      ]
     },
     "execution_count": 226,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "songs_index"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.基于模型的协同过滤"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 初始化参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 285,
   "metadata": {},
   "outputs": [],
   "source": [
    "from numpy.random import random\n",
    "K=20\n",
    "bi=np.zeros(n_songs)\n",
    "bu=np.zeros(n_users)\n",
    "P=random((n_users,K))/10*(np.sqrt(K))\n",
    "Q=random((K,n_songs))/10*(np.sqrt(K))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 286,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_samples=data.shape[0]\n",
    "mu=0.0\n",
    "uids=[]  #记录用户索引\n",
    "i_ids=[]  #记录歌曲的索引\n",
    "R=np.matrix(np.zeros(shape=(n_users,n_songs)),float)\n",
    "for i in range(n_samples):\n",
    "    uid=users_index[data.iloc[i][\"user\"]] #用户\n",
    "    iid=songs_index[data.iloc[i][\"song\"]] # 歌曲\n",
    "    uids.append(uid)\n",
    "    i_ids.append(iid)\n",
    "    R[uid,iid]=data.iloc[i][\"fractional_play_count\"]\n",
    "    mu+=R[uid,iid]\n",
    "mu /=n_samples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 287,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.021055998294197832"
      ]
     },
     "execution_count": 287,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mu"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据参数，预测用户uid对歌曲(iid)的打分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 288,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pred_SVD(uid,i_id):\n",
    "    score=mu+bi[i_id]+bu[uid]+np.dot(P[uid,:],Q[:,i_id])\n",
    "    return score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 290,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 is running!\n",
      "the rmse of 0 step on train data is: 983.1988984868112\n",
      "1 is running!\n",
      "the rmse of 1 step on train data is: 105.57266367237823\n",
      "2 is running!\n",
      "the rmse of 2 step on train data is: 95.01631172582576\n",
      "3 is running!\n",
      "the rmse of 3 step on train data is: 90.4086504562999\n",
      "4 is running!\n",
      "the rmse of 4 step on train data is: 87.68208507430468\n",
      "5 is running!\n",
      "the rmse of 5 step on train data is: 85.51544935492706\n",
      "6 is running!\n",
      "the rmse of 6 step on train data is: 83.87604029189418\n",
      "7 is running!\n",
      "the rmse of 7 step on train data is: 82.56058842478627\n",
      "8 is running!\n",
      "the rmse of 8 step on train data is: 81.48076911053823\n",
      "9 is running!\n",
      "the rmse of 9 step on train data is: 80.55171589706063\n",
      "10 is running!\n",
      "the rmse of 10 step on train data is: 79.73703249367037\n",
      "11 is running!\n",
      "the rmse of 11 step on train data is: 79.01802283034749\n",
      "12 is running!\n",
      "the rmse of 12 step on train data is: 78.45748673883071\n",
      "13 is running!\n",
      "the rmse of 13 step on train data is: 77.89444984479441\n",
      "14 is running!\n",
      "the rmse of 14 step on train data is: 77.37860633000668\n",
      "15 is running!\n",
      "the rmse of 15 step on train data is: 76.9590534635534\n",
      "16 is running!\n",
      "the rmse of 16 step on train data is: 76.56017971004268\n",
      "17 is running!\n",
      "the rmse of 17 step on train data is: 76.21646248462477\n",
      "18 is running!\n",
      "the rmse of 18 step on train data is: 75.82940258630128\n",
      "19 is running!\n",
      "the rmse of 19 step on train data is: 75.61219078376513\n",
      "20 is running!\n",
      "the rmse of 20 step on train data is: 75.31589902439995\n",
      "21 is running!\n",
      "the rmse of 21 step on train data is: 75.0993028933003\n",
      "22 is running!\n",
      "the rmse of 22 step on train data is: 74.84638959606957\n",
      "23 is running!\n",
      "the rmse of 23 step on train data is: 74.65263640089834\n",
      "24 is running!\n",
      "the rmse of 24 step on train data is: 74.48614194400463\n",
      "25 is running!\n",
      "the rmse of 25 step on train data is: 74.29143332291704\n",
      "26 is running!\n",
      "the rmse of 26 step on train data is: 74.11078573066497\n",
      "27 is running!\n",
      "the rmse of 27 step on train data is: 73.99185946293015\n",
      "28 is running!\n",
      "the rmse of 28 step on train data is: 73.87535420978676\n",
      "29 is running!\n",
      "the rmse of 29 step on train data is: 73.74723433956947\n",
      "30 is running!\n",
      "the rmse of 30 step on train data is: 73.62620973501008\n",
      "31 is running!\n",
      "the rmse of 31 step on train data is: 73.51790540156642\n",
      "32 is running!\n",
      "the rmse of 32 step on train data is: 73.42976401022202\n",
      "33 is running!\n",
      "the rmse of 33 step on train data is: 73.34387063800607\n",
      "34 is running!\n",
      "the rmse of 34 step on train data is: 73.25968754228946\n",
      "35 is running!\n",
      "the rmse of 35 step on train data is: 73.17361362656712\n",
      "36 is running!\n",
      "the rmse of 36 step on train data is: 73.10418440189002\n",
      "37 is running!\n",
      "the rmse of 37 step on train data is: 73.04406246882917\n",
      "38 is running!\n",
      "the rmse of 38 step on train data is: 72.97922427266954\n",
      "39 is running!\n",
      "the rmse of 39 step on train data is: 72.92093203198795\n",
      "40 is running!\n",
      "the rmse of 40 step on train data is: 72.86513912483741\n",
      "41 is running!\n",
      "the rmse of 41 step on train data is: 72.8123361535855\n",
      "42 is running!\n",
      "the rmse of 42 step on train data is: 72.77418345926404\n",
      "43 is running!\n",
      "the rmse of 43 step on train data is: 72.73200510669257\n",
      "44 is running!\n",
      "the rmse of 44 step on train data is: 72.69362845160974\n",
      "45 is running!\n",
      "the rmse of 45 step on train data is: 72.65769899022746\n",
      "46 is running!\n",
      "the rmse of 46 step on train data is: 72.62299196775871\n",
      "47 is running!\n",
      "the rmse of 47 step on train data is: 72.58973632419054\n",
      "48 is running!\n",
      "the rmse of 48 step on train data is: 72.55877538864007\n",
      "49 is running!\n",
      "the rmse of 49 step on train data is: 72.53448394986442\n"
     ]
    }
   ],
   "source": [
    "n_steps=50\n",
    "gamma=0.04\n",
    "Lambda=0.15\n",
    "for i in range(n_steps):\n",
    "    print(\"%d is running!\"%i)\n",
    "    rmse_sum=0.0\n",
    "    kk=np.random.permutation(n_samples) #将样本随机化\n",
    "    for j in range(n_samples):\n",
    "        index=kk[j]\n",
    "        uid=uids[index]\n",
    "        iid=i_ids[index]\n",
    "        \n",
    "        eui=R[uid,iid]- pred_SVD(uid,iid) #预测残差\n",
    "        rmse_sum+=eui**2 #残差平方和\n",
    "        #随机梯度下降\n",
    "        bu[uid]+=gamma*(eui-Lambda*bu[uid])\n",
    "        bi[iid]+=gamma*(eui-Lambda*bi[iid])\n",
    "        for k in range(K):\n",
    "            #P,Q同时更新\n",
    "            temp=P[uid,k]+gamma*eui*Q[k,iid]-Lambda*P[uid,k]\n",
    "            Q[k,iid]+=gamma*eui*P[uid,k]-Lambda*Q[k,iid]\n",
    "            P[uid,k]=temp\n",
    "    #学习率递减\n",
    "    gamma=gamma*0.93\n",
    "    print(\"the rmse of %d step on train data is:\"%i,rmse_sum)\n",
    "            \n",
    "            \n",
    "        "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "计算用户对每首歌曲的预测打分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 300,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.02264335, 0.        , 0.02734985, 0.03522976, 0.02785343,\n",
       "       0.01793746, 0.02546478, 0.        , 0.02089062, 0.02295235,\n",
       "       0.02476338, 0.02776363, 0.04219538, 0.02592834, 0.02770142,\n",
       "       0.02089924, 0.02541838, 0.03396559, 0.0376075 , 0.        ,\n",
       "       0.01913137, 0.02022399, 0.02671411, 0.02937564, 0.02650215,\n",
       "       0.02077787, 0.02094168, 0.02083946, 0.02284696, 0.01798858,\n",
       "       0.02263044, 0.02382715, 0.02330729, 0.02185828, 0.03266343,\n",
       "       0.02874622, 0.        , 0.02634531, 0.02088915, 0.04251557,\n",
       "       0.02943508, 0.02356248, 0.04160473, 0.03368917, 0.02334571,\n",
       "       0.02028715, 0.02404937, 0.02713369, 0.02257981, 0.02364858,\n",
       "       0.03204237, 0.02042907, 0.02955873, 0.03076899, 0.0221094 ,\n",
       "       0.02576761, 0.02334745, 0.03132634, 0.01634305, 0.03029141,\n",
       "       0.02041716, 0.02335032, 0.02803107, 0.02457857, 0.02641288,\n",
       "       0.02616693, 0.01889223, 0.02415235, 0.04021451, 0.01788448,\n",
       "       0.02712887, 0.01875009, 0.02602689, 0.02993319, 0.01969205,\n",
       "       0.0561674 , 0.03387344, 0.01763107, 0.0211373 , 0.02580175,\n",
       "       0.02009871, 0.01664974, 0.01935788, 0.02750143, 0.02855788,\n",
       "       0.03787799, 0.03757343, 0.01986308, 0.02715152, 0.01748472,\n",
       "       0.02433084, 0.02285635, 0.02797967, 0.0212429 , 0.02209748,\n",
       "       0.04150288, 0.02595023, 0.02240994, 0.04025002, 0.02852666,\n",
       "       0.02106201, 0.03380682, 0.02729974, 0.02056168, 0.02006634,\n",
       "       0.0319484 , 0.02433961, 0.05155494, 0.0277977 , 0.02562302,\n",
       "       0.02324354, 0.01933941, 0.02394785, 0.03073051, 0.        ,\n",
       "       0.02463978, 0.02801935, 0.0274115 , 0.02503644, 0.01838979,\n",
       "       0.02180311, 0.02107841, 0.0494509 , 0.01805762, 0.04030289,\n",
       "       0.02676735, 0.02373643, 0.02238765, 0.02298454, 0.03232426,\n",
       "       0.03265594, 0.02311156, 0.01735333, 0.0264312 , 0.0450634 ,\n",
       "       0.04066477, 0.01938213, 0.02676123, 0.02252643, 0.01906073,\n",
       "       0.02873814, 0.        , 0.02682581, 0.02405789, 0.02445282,\n",
       "       0.02063767, 0.02096583, 0.03244318, 0.0177624 , 0.02980023,\n",
       "       0.0488102 , 0.02014649, 0.03011125, 0.01696254, 0.02877283,\n",
       "       0.05439138, 0.03549716, 0.01334236, 0.01882739, 0.02094123,\n",
       "       0.02375245, 0.        , 0.02639574, 0.0277563 , 0.01899975,\n",
       "       0.02168565, 0.02456211, 0.02887301, 0.02531044, 0.01564145,\n",
       "       0.0289712 , 0.02276473, 0.05141461, 0.03114472, 0.02319096,\n",
       "       0.02883188, 0.0246277 , 0.02712097, 0.02403598, 0.0247071 ,\n",
       "       0.02558326, 0.03583818, 0.03477503, 0.02212154, 0.02104391,\n",
       "       0.02786007, 0.05360191, 0.02162668, 0.03363475, 0.0208178 ,\n",
       "       0.01477441, 0.01603048, 0.        , 0.03251899, 0.02538714,\n",
       "       0.03656385, 0.06721002, 0.04042855, 0.02584721, 0.02361817,\n",
       "       0.02790846, 0.02356442, 0.02861063, 0.0246962 , 0.02365106,\n",
       "       0.02286845, 0.02255237, 0.02281247, 0.02519208, 0.03910608,\n",
       "       0.        , 0.02361475, 0.02576808, 0.02138682, 0.02334748,\n",
       "       0.02257541, 0.02300155, 0.0251265 , 0.02865651, 0.0230889 ,\n",
       "       0.02465402, 0.01829713, 0.02177815, 0.03036367, 0.02409383,\n",
       "       0.04401903, 0.02436025, 0.02877756, 0.        , 0.02062429,\n",
       "       0.02329712, 0.02265969, 0.02197217, 0.02111442, 0.01666771,\n",
       "       0.01775254, 0.        , 0.04528399, 0.02193898, 0.02096028,\n",
       "       0.01944625, 0.02688712, 0.02554104, 0.02477321, 0.02355604,\n",
       "       0.02326759, 0.01953487, 0.01788911, 0.01973162, 0.02468525,\n",
       "       0.0376452 , 0.03675541, 0.02247398, 0.02901877, 0.02399475,\n",
       "       0.0252269 , 0.01822964, 0.02211952, 0.04959006, 0.03571835,\n",
       "       0.02738334, 0.0235388 , 0.03191694, 0.02690563, 0.02477328,\n",
       "       0.01996727, 0.0211908 , 0.02921097, 0.02701923, 0.02578411,\n",
       "       0.02874509, 0.02508339, 0.        , 0.01864794, 0.01859415,\n",
       "       0.01921652, 0.03676812, 0.02292668, 0.02704995, 0.02819649,\n",
       "       0.0298881 , 0.03854795, 0.02561861, 0.01974348, 0.03615249,\n",
       "       0.02926137, 0.03728756, 0.02179995, 0.01718104, 0.01842484,\n",
       "       0.02374329, 0.02391779, 0.01951126, 0.02288254, 0.02109129,\n",
       "       0.03400303, 0.02057248, 0.02381219, 0.02604662, 0.03086763,\n",
       "       0.02038189, 0.02149028, 0.02161181, 0.02710516, 0.02508837,\n",
       "       0.02314696, 0.02648336, 0.02520003, 0.02261694, 0.02381906,\n",
       "       0.02874183, 0.0252041 , 0.00868708, 0.04205943, 0.02866672,\n",
       "       0.05100619, 0.03448646, 0.0299656 , 0.02732856, 0.01684372,\n",
       "       0.01829145, 0.0178346 , 0.0252224 , 0.03591153, 0.04138343,\n",
       "       0.04178426, 0.02303357, 0.02681788, 0.02513623, 0.0382704 ,\n",
       "       0.03638187, 0.10817807, 0.03047953, 0.02400342, 0.02146582,\n",
       "       0.02812741, 0.01618012, 0.03050482, 0.02043218, 0.        ,\n",
       "       0.        , 0.02509007, 0.02072496, 0.0330272 , 0.02301156,\n",
       "       0.02598929, 0.02702531, 0.02544043, 0.0297606 , 0.03066456,\n",
       "       0.02477623, 0.04498995, 0.02804994, 0.02528931, 0.04636781,\n",
       "       0.03764401, 0.02303979, 0.02200639, 0.02677554, 0.02825273,\n",
       "       0.0305427 , 0.02416826, 0.02181533, 0.0170089 , 0.02282255,\n",
       "       0.04057424, 0.02406238, 0.02401271, 0.02725669, 0.02381038,\n",
       "       0.04622015, 0.        , 0.02521209, 0.02196637, 0.03126844,\n",
       "       0.02601982, 0.03069649, 0.0222126 , 0.04060947, 0.02745928,\n",
       "       0.02615215, 0.        , 0.0176741 , 0.02132731, 0.0190159 ,\n",
       "       0.02555481, 0.01757754, 0.        , 0.02767902, 0.02547019,\n",
       "       0.03456417, 0.02419315, 0.02435343, 0.03131333, 0.04118926,\n",
       "       0.02171716, 0.02413188, 0.02329275, 0.0286204 , 0.02786336,\n",
       "       0.        , 0.02077894, 0.03541226, 0.02071533, 0.03137625,\n",
       "       0.0224974 , 0.02454399, 0.02339626, 0.02640115, 0.02197973,\n",
       "       0.02964128, 0.02498918, 0.        , 0.01719237, 0.02245945,\n",
       "       0.02933726, 0.01869154, 0.0258416 , 0.01856709, 0.02376298,\n",
       "       0.02232867, 0.02001301, 0.02411493, 0.0257718 , 0.02871601,\n",
       "       0.02731395, 0.0340139 , 0.03081877, 0.02816867, 0.04354089,\n",
       "       0.02804192, 0.0429187 , 0.030424  , 0.0308471 , 0.02568503,\n",
       "       0.02262138, 0.03216319, 0.05561384, 0.03737532, 0.04047845,\n",
       "       0.0320131 , 0.02345373, 0.03819746, 0.02533479, 0.02245154,\n",
       "       0.02120688, 0.02639126, 0.05067558, 0.02198129, 0.        ,\n",
       "       0.        , 0.01322325, 0.02207053, 0.02643877, 0.        ,\n",
       "       0.0251823 , 0.02308761, 0.01758731, 0.02729845, 0.02999472,\n",
       "       0.02854462, 0.02123472, 0.0250853 , 0.02548699, 0.02783052,\n",
       "       0.0224939 , 0.03824125, 0.02374192, 0.02703793, 0.03456834,\n",
       "       0.02260415, 0.02860781, 0.02304732, 0.0242422 , 0.020717  ,\n",
       "       0.02564988, 0.02089227, 0.02640309, 0.02068217, 0.02136872,\n",
       "       0.04886745, 0.03140506, 0.04097126, 0.01900449, 0.03235228,\n",
       "       0.03574701, 0.04396574, 0.01726976, 0.02181799, 0.02561714,\n",
       "       0.01670682, 0.01764535, 0.02595079, 0.02596059, 0.03024983,\n",
       "       0.02131011, 0.02993712, 0.01724325, 0.0296027 , 0.01736164,\n",
       "       0.0192083 , 0.02126138, 0.02773321, 0.02112666, 0.02635363,\n",
       "       0.03827751, 0.04306362, 0.02149739, 0.05765993, 0.03471698,\n",
       "       0.02515841, 0.02602394, 0.03903446, 0.04081672, 0.02552807,\n",
       "       0.02512762, 0.02957901, 0.01771303, 0.00999693, 0.01922991,\n",
       "       0.02801401, 0.0180634 , 0.02005839, 0.02380831, 0.04924568,\n",
       "       0.01971529, 0.01862528, 0.0252275 , 0.03129254, 0.03888876,\n",
       "       0.01875065, 0.05504175, 0.02410166, 0.02527212, 0.02143146,\n",
       "       0.02159545, 0.0221886 , 0.02438716, 0.0608289 , 0.03518821,\n",
       "       0.0239543 , 0.03076119, 0.02930078, 0.02002629, 0.02118962,\n",
       "       0.02532541, 0.02285062, 0.02813045, 0.09709977, 0.02047921,\n",
       "       0.0265414 , 0.02564449, 0.0291329 , 0.        , 0.02224583,\n",
       "       0.02143167, 0.04007975, 0.        , 0.02313804, 0.01657464,\n",
       "       0.        , 0.01374995, 0.02490484, 0.0483614 , 0.01976143,\n",
       "       0.0250885 , 0.02367191, 0.02262809, 0.02683835, 0.01835695,\n",
       "       0.02977364, 0.01826354, 0.02031277, 0.02815838, 0.        ,\n",
       "       0.01694934, 0.0252731 , 0.02094669, 0.0283718 , 0.03899899,\n",
       "       0.05754997, 0.0259915 , 0.01797885, 0.02386466, 0.021033  ,\n",
       "       0.02413176, 0.03134207, 0.03873347, 0.02584814, 0.06030177,\n",
       "       0.01991626, 0.05203461, 0.        , 0.02301475, 0.02333624,\n",
       "       0.0249863 , 0.02391494, 0.02483769, 0.04345701, 0.02759816,\n",
       "       0.02272247, 0.02458714, 0.02842747, 0.02917794, 0.02950518,\n",
       "       0.03043546, 0.02352393, 0.01612257, 0.02156929, 0.01557968,\n",
       "       0.03534289, 0.04003483, 0.02392807, 0.02073648, 0.        ,\n",
       "       0.03220246, 0.02137644, 0.01981174, 0.03527722, 0.02430059,\n",
       "       0.03544422, 0.02017956, 0.04675549, 0.01744017, 0.03418092,\n",
       "       0.01146301, 0.03980547, 0.03152459, 0.02024395, 0.01743369,\n",
       "       0.04064401, 0.04253692, 0.02181544, 0.01767809, 0.04726315,\n",
       "       0.01275066, 0.0424402 , 0.01500795, 0.02189326, 0.03408358,\n",
       "       0.07073929, 0.02435866, 0.01428326, 0.03181391, 0.02686823,\n",
       "       0.02143212, 0.02818585, 0.02329688, 0.02318164, 0.03004484,\n",
       "       0.02213021, 0.01732459, 0.02520255, 0.02350036, 0.03732973,\n",
       "       0.02882885, 0.02935554, 0.02076988, 0.0215263 , 0.04238511,\n",
       "       0.01731607, 0.0517773 , 0.03460936, 0.02227153, 0.01722384,\n",
       "       0.03155773, 0.02616327, 0.04286249, 0.02673392, 0.0279596 ,\n",
       "       0.02301391, 0.03925648, 0.02609571, 0.02293302, 0.01137826,\n",
       "       0.01939623, 0.03032371, 0.02837846, 0.04938833, 0.02165934,\n",
       "       0.02693125, 0.02612207, 0.02931223, 0.01907876, 0.01726287,\n",
       "       0.02339956, 0.        , 0.02167592, 0.01685581, 0.03249326,\n",
       "       0.03671001, 0.02841412, 0.02577638, 0.02479819, 0.04149058,\n",
       "       0.03199179, 0.02453424, 0.02909516, 0.03179267, 0.02167744,\n",
       "       0.0263184 , 0.03039677, 0.01869594, 0.03634232, 0.02500126,\n",
       "       0.02456536, 0.        , 0.0211161 , 0.06654981, 0.01746233,\n",
       "       0.03246833, 0.03425907, 0.02551657, 0.        , 0.02887518,\n",
       "       0.05266061, 0.02274633, 0.02182316, 0.04036437, 0.02024572,\n",
       "       0.01071224, 0.02416997, 0.02147517, 0.02145727, 0.02108117,\n",
       "       0.04359965, 0.02774979, 0.02188075, 0.02649552, 0.01973819,\n",
       "       0.02221865, 0.026055  , 0.02684472, 0.01519802, 0.02460316,\n",
       "       0.02606699, 0.03265319, 0.03715048, 0.01828536, 0.02449685,\n",
       "       0.02684287, 0.00975842, 0.03273852, 0.10029495, 0.0426014 ,\n",
       "       0.03153696, 0.02031184, 0.        , 0.01594325, 0.02548032,\n",
       "       0.02363523, 0.03002297, 0.01954717, 0.02002358, 0.02774677,\n",
       "       0.02686697, 0.02042779, 0.01793346, 0.01903814, 0.02396449,\n",
       "       0.03524087, 0.02800109, 0.02215585, 0.02361814, 0.02188354,\n",
       "       0.04067678, 0.02315642, 0.02378027, 0.04336309, 0.0234841 ,\n",
       "       0.05031087, 0.01963574, 0.0207648 , 0.0210383 , 0.01992815,\n",
       "       0.01572296, 0.02635816, 0.0237781 , 0.        , 0.01767806,\n",
       "       0.02540144, 0.02938759, 0.02239685, 0.01938832, 0.        ,\n",
       "       0.01165279, 0.01842194, 0.02854389, 0.02077967, 0.02213172,\n",
       "       0.01649524, 0.02295294, 0.0234985 , 0.02014183, 0.02379004,\n",
       "       0.02124618, 0.02158956, 0.02222044, 0.01928305, 0.01704994])"
      ]
     },
     "execution_count": 300,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cur_user=users[89]\n",
    "cur_user_id=users_index[cur_user]\n",
    "cur_user_songs=user_songs[cur_user_id]\n",
    "\n",
    "similarity=0.0\n",
    "rat_acc=0.0\n",
    "\n",
    "user_songs_scores=np.zeros(n_songs)\n",
    "for i in range(n_songs):\n",
    "    if i not in cur_user_songs:\n",
    "        user_songs_scores[i]=pred_SVD(cur_user_id,i)\n",
    "user_songs_scores"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据预测打分去对用户进行推荐"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 301,
   "metadata": {},
   "outputs": [],
   "source": [
    "sort_index=sorted(((e,i) for i,e in enumerate(list(user_songs_scores))),reverse=True)\n",
    "columns=[\"user_id\",\"song\",\"score\",\"rank\"]\n",
    "df=pd.DataFrame(columns=columns)\n",
    "rank=1\n",
    "for i in range(len(sort_index)):\n",
    "    cur_song_index=sort_index[i][1]\n",
    "    cur_song=list(songs_index.keys())[list(songs_index.values()).index(cur_song_index)]\n",
    "    if ~np.isnan(sort_index[i][0]) and cur_song_index not in cur_user_songs and rank<21:\n",
    "        df.loc[len(df)]=[cur_user,cur_song,sort_index[i][0],rank]\n",
    "        rank+=1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 302,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>song</th>\n",
       "      <th>score</th>\n",
       "      <th>rank</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOYPWKK12A8C136494</td>\n",
       "      <td>0.108178</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOTLHUV12A6D4FC541</td>\n",
       "      <td>0.100295</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOXFYTY127E9433E7D</td>\n",
       "      <td>0.097100</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SORWLJM12A6D4F9C0C</td>\n",
       "      <td>0.070739</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOBONKR12A58A7A7E0</td>\n",
       "      <td>0.067210</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOVVBPK12A58A810CA</td>\n",
       "      <td>0.066550</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOSCDWE12AB01823C4</td>\n",
       "      <td>0.060829</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOQBMFK12A8C13835B</td>\n",
       "      <td>0.060302</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOXCCPU12A58A7BF1E</td>\n",
       "      <td>0.057660</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOITRTA12A6D4F8261</td>\n",
       "      <td>0.057550</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOULBNJ12AB01851E9</td>\n",
       "      <td>0.056167</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOVGLTY12AF72A39CD</td>\n",
       "      <td>0.055614</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOQQAAQ12A67ADE34D</td>\n",
       "      <td>0.055042</td>\n",
       "      <td>13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOWGDDU12AF72A03DA</td>\n",
       "      <td>0.054391</td>\n",
       "      <td>14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOVMGXI12AF72A80B0</td>\n",
       "      <td>0.053602</td>\n",
       "      <td>15</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOTUARP12A8C13CB54</td>\n",
       "      <td>0.052661</td>\n",
       "      <td>16</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SORJBJB12A8C13E711</td>\n",
       "      <td>0.052035</td>\n",
       "      <td>17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOZQRSR12A6701E2F7</td>\n",
       "      <td>0.051777</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOXPZEZ12A8AE48AC9</td>\n",
       "      <td>0.051555</td>\n",
       "      <td>19</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>e0152edeec1154b620b083fbb095f1f0f4de5e2e</td>\n",
       "      <td>SOYAIPB12A8C143D84</td>\n",
       "      <td>0.051415</td>\n",
       "      <td>20</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     user_id                song     score  \\\n",
       "0   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOYPWKK12A8C136494  0.108178   \n",
       "1   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOTLHUV12A6D4FC541  0.100295   \n",
       "2   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOXFYTY127E9433E7D  0.097100   \n",
       "3   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SORWLJM12A6D4F9C0C  0.070739   \n",
       "4   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOBONKR12A58A7A7E0  0.067210   \n",
       "5   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOVVBPK12A58A810CA  0.066550   \n",
       "6   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOSCDWE12AB01823C4  0.060829   \n",
       "7   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOQBMFK12A8C13835B  0.060302   \n",
       "8   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOXCCPU12A58A7BF1E  0.057660   \n",
       "9   e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOITRTA12A6D4F8261  0.057550   \n",
       "10  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOULBNJ12AB01851E9  0.056167   \n",
       "11  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOVGLTY12AF72A39CD  0.055614   \n",
       "12  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOQQAAQ12A67ADE34D  0.055042   \n",
       "13  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOWGDDU12AF72A03DA  0.054391   \n",
       "14  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOVMGXI12AF72A80B0  0.053602   \n",
       "15  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOTUARP12A8C13CB54  0.052661   \n",
       "16  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SORJBJB12A8C13E711  0.052035   \n",
       "17  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOZQRSR12A6701E2F7  0.051777   \n",
       "18  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOXPZEZ12A8AE48AC9  0.051555   \n",
       "19  e0152edeec1154b620b083fbb095f1f0f4de5e2e  SOYAIPB12A8C143D84  0.051415   \n",
       "\n",
       "   rank  \n",
       "0     1  \n",
       "1     2  \n",
       "2     3  \n",
       "3     4  \n",
       "4     5  \n",
       "5     6  \n",
       "6     7  \n",
       "7     8  \n",
       "8     9  \n",
       "9    10  \n",
       "10   11  \n",
       "11   12  \n",
       "12   13  \n",
       "13   14  \n",
       "14   15  \n",
       "15   16  \n",
       "16   17  \n",
       "17   18  \n",
       "18   19  \n",
       "19   20  "
      ]
     },
     "execution_count": 302,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "准确率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 303,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "准确率是： 0.029411764705882353\n"
     ]
    }
   ],
   "source": [
    "user_song_true=[]\n",
    "for i,j in songs_index.items():\n",
    "    if j in cur_user_songs:\n",
    "        user_song_true.append(i)\n",
    "user_song_true=set(user_song_true)\n",
    "user_song_prd=set(df.song.values)\n",
    "precision=len(user_song_true.intersection(user_songs_prd))/len(user_song_true)\n",
    "print(\"准确率是：\",precision)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "召回率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 304,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "召回率是： 0.05\n"
     ]
    }
   ],
   "source": [
    "recall=len(user_song_true.intersection(user_songs_prd))/len(user_songs_prd)\n",
    "print(\"召回率是：\",recall)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
